package Control;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;

import objects.Chromosome;
import objects.Gene;
import objects.Treatment;

import Interfaces.State;

/**
 * 
 * @author stephenbwilliamson
 */
public class Controller {

	private Gene currentGene;
	private State currentState;
	private List<Treatment> currentTreatments;
	private List<Chromosome> chromosomes;
	private List<Gene> genes;
	private List<Integer> activeTreatments;
	private static Controller instance = null;
	private boolean collapse = false;
	private int nextColor = 0;
	private Color[] colors = { new Color(0, 160, 176), // Invisible UFO -
			new Color(106, 74, 60), // 432~caribic brow - Brown
			new Color(204, 51, 63), // 433~caribic red - Red
			new Color(235, 104, 65), // 434~caribic sun - Orange
			new Color(237, 201, 81), // 435~caribic day - Yellow
			new Color(85, 98, 112), // Mighty Slate - Slate
			new Color(78, 205, 196), // Pacifica - Light Blue-Green
			new Color(199, 244, 100), // Apple Chic - Light Green
			new Color(255, 107, 107), // Cherry Pink - Pinkish Red
			new Color(196, 77, 88), // Grandma's Pillow - Darkish Red
			new Color(255, 153, 0), // Vitamin C - Orange
			new Color(66, 66, 66), // Route 66 - Dark Grey
			new Color(50, 153, 187), // Gamebookers Blue - Blue
			new Color(233, 233, 233), // Steady Grey - Light Grey
			new Color(188, 188, 188), // BC - Grey
			new Color(209, 231, 81), // Limey - Lime Green
			new Color(77, 188, 233), // Electric Blue - Vivid Blue
			new Color(38, 173, 228), // Blube - Vivid Blue
			new Color(250, 208, 137), // Walls - Muted Yellow
			new Color(255, 155, 91), // Yamabuki - Orange
			new Color(245, 99, 74), // Manic Craving - Red-Orange
			new Color(237, 48, 60), // What I Believe - Red
			new Color(59, 129, 131), // Managed Arm - Green-Blue
	};

	private static int geneOffset = 1200;

	public Color getRandomColor() {
		if (nextColor > colors.length)
			nextColor = 0;
		return colors[nextColor++];
	}

	protected Controller() {
		chromosomes = new ArrayList<Chromosome>();
		genes = new ArrayList<Gene>();
		currentTreatments = new ArrayList<Treatment>();
		activeTreatments = new ArrayList<Integer>();
	}

	public void collapseSubsets() {
		collapse = true;
	}

	public void showAllSubsets() {
		collapse = false;
	}

	public boolean isCollapsed() {
		return collapse;
	}

	public static Controller getInstance() {
		if (instance == null) {
			instance = new Controller();
		}
		return instance;
	}

	/**
	 * Sets the currentGene to be the new Gene. When a new gene is set, this
	 * method also makes sure that the [code]state[/code] knows that an update
	 * has occurred and calls the refresh method of State.
	 * 
	 * @param newGene
	 */
	public void setCurrentGene(Gene newGene) {
		if (newGene.equals(currentGene)) {
			return;
		}

		currentGene = newGene;
		if (currentState != null) {
			currentState.refresh();
		}
	}

	public int getCalculatedDistance() {
		if (currentGene != null)
			return currentGene.getValidDistance() + 2 * geneOffset;
		else
			return -1;
	}

	public int getOffset() {
		return geneOffset;
	}

	/**
	 * Returns the current gene model. This allows the state to visually display
	 * the information required from the Gene.
	 */
	public Gene getCurrentGene() {
		return currentGene;
	}

	public void setTreatment(Integer i) {
		activeTreatments.add(i);
	}

	public void removeTreatment(Integer treatment) {
		activeTreatments.remove(treatment);
	}

	public Treatment getLastTreatment() {
		return (activeTreatments.isEmpty()) ? null : currentGene
				.getTreatmentByID(activeTreatments.get(treatmentSize() - 1));
	}

	public List<Integer> getActiveTreatments() {
		return activeTreatments;
	}

	public void clearTreatments() {
		activeTreatments.removeAll(activeTreatments);
	}

	public int treatmentSize() {
		return activeTreatments.size();
	}

	/**
	 * Sets the new state (drawing method) for the current application. This
	 * allows each state to manage the view separately, and allows for future
	 * 'view' management
	 * 
	 * @param newState
	 */
	public void setState(State newState) {
		if (!currentState.equals(newState)) {
			currentState.endState();
			currentState = newState;
		}
		if (currentState != null) {
			currentState.refresh();
		}
	}

	/**
	 * Returns the current activated state.
	 * 
	 * @return
	 */
	public State getActiveState() {
		return currentState;
	}

	public void addChromosome(Chromosome ch) {
		if (!chromosomes.contains(ch)) {
			chromosomes.add(ch);
		}
	}

	public void addGene(Gene gene) {
		if (!genes.contains(gene)) {
			genes.add(gene);
		}
	}

	public List<Chromosome> getChromosomeList() {
		return chromosomes;
	}

	public List<Gene> getGeneList() {
		return genes;
	}

	public void setActiveTreatment(Treatment t) {
		if (!currentTreatments.contains(t)) {
			currentTreatments.add(t);

		}
	}

	public void removeActiveTreatment(Treatment t) {
		if (currentTreatments.contains(t)) {
			currentTreatments.remove(t);
		}
	}
}
